/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "MCT8316ADriver.h"
#include "bsp_dwt.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
static MCT8316A_Instance_s *MCT8316A_Instance = NULL;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
static MCT8316A_reg_s Reg;
static MCT8316A_reg_s SYS_Reg;
static uint32_t MOTOR_SPEED;
static uint32_t CMD_SPEED;
static uint32_t CONTROLLER_FAULT_STATUS;
static uint32_t GATE_DRIVER_FAULT_STATUS;
typedef enum
{
  SYSTEM_IDLE = 0,
  MOTOR_STARTUP,
  MOTOR_RUNNING,
  SYSTEM_INIT,
  MOTOR_IPD,
  MOTOR_ALIGN,
  MOTOR_IDLE,
  MOTOR_STOP,
  FAULT,
  MOTOR_DIRECTION,
  HALL_ALIGN,
  MOTOR_FREEWHEEL,
  MOTOR_DESCEL,
  MOTOR_BREAK,
} MCT8316A_State_e;
MCT8316A_State_e State;
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  /* USER CODE BEGIN 2 */
  DWT_Init(168);
  CMD_SPEED = 40;
  MCT8316A_conf_s conf = {
      .iic_conf = {
          .dev_address = 0x00,
          .work_mode = IIC_BLOCK_MODE,
          .handle = &hi2c2,
      },
      .ISD_CONFIG = {
          .ISD_SWITCH = ISD_EN,
          .BREAK_SWITCH = BREAK_EN,
          .HiZ_SWITCH = HIZ_DIS,
          .RVS_SWITCH = RVS_DR_EN,
          .RESYNC_SWITCH = RESYNC_EN,
          .STAT_BRK_SWITCH = STAT_BRK_EN,
          .STAT_DETECT_THR = STAT_DETECT_THR_25mV,
      },
      .MOTOR_STARTUP1 = {
          .MTR_STARTUP = MTR_STARTUP_Slow_First_Cycle,
          .ALIGN_RAMP_RATE = ALIGN_RAMP_RATE_5Vs,
          .ALIGN_TIME = ALIGN_TIME_6s,
          .ALIGN_CURR_THR = ALIGN_CURR_THR_0d4V,
          .IPD_CLK_FREQ = IPD_CLK_FREQ_250Hz,
          .IPD_CURR_THR = IPD_CURR_THR_0d4V,
          .IPD_RLS_MODE = IPD_RLS_MODE_Tristate,
          .IPD_ADV_ANGLE = IPD_ADV_ANGLE_60_DEG,
          .IPD_REPEAT = IPD_REPEAT_2,
          .SLOW_FIRST_CYC_FREQ = SLOW_FIRST_CYC_FREQ_0d5Hz,
      },
      .MOTOR_STARTUP2 = {
          .OL_current_limit_conf = OL_ILIMIT_CONFIG,
          .OL_ILIMIT = OL_ILIMIT_0d5V,
          .OL_DUTY_LIMIT = OL_DUTY_LIMIT_50,
          .OL_ACC_A1 = OL_ACC_A1_0d25Hzs,
          .OL_ACC_A2 = OL_ACC_A2_5Hzs2,
          .AUTO_HANDOFF = AUTO_HANDOFF_DIS,
          .OPN_CL_HANDOFF_THR = OPN_CL_HANDOFF_THR_400Hz,
          .FIRST_CYCLE_FREQ_SEL = FIRST_CYCLE_FREQ_SEL_SLOW,
          .MIN_DUTY = MIN_DUTY_10,
      },
      .CLOSED_LOOP1 = {
          .COMM_CONTROL = COMM_CONTROL_120DEG,
          .CL_ACC = CL_ACC_1Vs,
          .CL_DEC = CL_DEC_1Vs,
          .PWM_FREQ_OUT = PWM_FREQ_OUT_40k,
          .LD_ANGLE_POLARITY = LD_ANGLE_POLARITY_POSITIVE,
          .LD_ANGLE = (uint32_t)(10.0f / 0.12) << 1,
      },
      .CLOSED_LOOP2 = {
          .FG_SEL = FG_SEL_OPENLOOP_AND_CLOSEDLOOP,
          .FG_DIV_FACTOR = FG_DIV_FACTOR_3,
          .CBC_ILIMIT = CBC_ILIMIT_0d5V,
          .ACT_SPIN_BRK_THR = ACT_SPIN_BRK_THR_7d5,
          .BRAKE_DUTY_THRESHOLD = BRAKE_DUTY_THRESHOLD_7d5,
          .FG_CONFIG = FG_CONFIG_THR,
          .FG_BEMF_THR = FG_BEMF_THR_1mV,
          .MTR_STOP = MTR_STOP_Recirculation,
          .MTR_STOP_BRK_TIME = MTR_STOP_BRK_TIME_1000ms,
          .AVS_SWITCH = AVS_ENABLE,
      },
      .CLOSED_LOOP3 = {
          .BEMF_THRESHOLD2 = BEMF_THRESHOLD2_0,
          .BEMF_THRESHOLD1 = BEMF_THRESHOLD1_200,
          .DYN_DEGAUSS = DYN_DEGAUSS_EN,
          .DEGAUSS_MAX_WIN = DEGAUSS_MAX_WIN_15,
          .DYN_DGS_FILT_COUNT = DYN_DGS_FILT_COUNT_3,
          .DYN_DGS_LOWER_LIM = DYN_DGS_LOWER_LIM_0d03V,
          .DYN_DGS_UPPER_LIM_VM = DYN_DGS_UPPER_LIM_VM_0d09V,
          .INTEG_CYCL_THR_HIGH = INTEG_CYCL_THR_HIGH_4,
          .INTEG_CYCL_THR_LOW = INTEG_CYCL_THR_LOW_3,
          .INTEG_DUTY_THR_HIGH = INTEG_DUTY_THR_HIGH_12,
          .INTEG_DUTY_THR_LOW = INTEG_DUTY_THR_LOW_12,
          .INTEG_ZC_METHOD = INTEG_ZC_METHOD_ZC_Based,
      },
      .CONST_SPEED = {
          .CLOSED_LOOP_MODE = CLOSED_LOOP_MODE_SPEEDLOOP,
          .SPD_POWER_V_MAX = SPD_POWER_V_MAX_100,
          .SPD_POWER_V_MIN = SPD_POWER_V_MIN_0,
          .SPD_POWER_KP = 5500 << 20,
          .SPD_POWER_KI = 40 << 10,
      },
      .CONST_PWR = {
          .MAX_SPEED = 60000 << 16,
          .MAX_POWER = 80 << 4,
      },
      .TRAP_CONFIG1 = {
          .OL_HANDOFF_CYCLES = OPEN_LOOP_HANDOFF_CYCLES_6,
      },
      .FAULT_CONFIG1 = {
          .MTR_LCK_MODE = MTR_LCK_MODE_9,
      },
      .FAULT_CONFIG2 = {
          .LOCK1 = LOCK1_EN,
          .LOCK2 = LOCK2_DIS,
          .LOCK3 = LOCK3_DIS,
          .LOCK_ABN_SPEED = LOCK_ABN_SPEED_4000Hz,
          .LOSS_SYNC_TIMES = LOSS_SYNC_TIMES_4,
          .NO_MTR_THR = NO_MTR_THR_0d005V,
      },
      .PIN_CONFIG1 = {
          .SPD_CTRL_MODE = SPD_CTRL_MODE_IIC,
      }};
  MCT8316A_Instance = MCT8316A_Init(&conf);
  DWT_Delay(0.2);
  Reg.addr = CLOSED_LOOP1_ADDR;
  MCT8316A_GetReg(MCT8316A_Instance, &Reg);
  DWT_Delay(0.2);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    Reg.addr = DEVICE_CTRL_ADDR;
    Reg.data = (CMD_SPEED * 32767 / 100) << 16;
    MCT8316A_SetReg(MCT8316A_Instance, &Reg);
    // Reg.addr = ALGO_CTRL1_ADDR;
    // Reg.data = 0x80000000;
    // MCT8316A_SetReg(MCT8316A_Instance, &Reg);
    // DWT_Delay(0.1);
    SYS_Reg.addr = SYS_STATUS2_ADDR;
    MCT8316A_GetReg(MCT8316A_Instance, &SYS_Reg);
    State = (SYS_Reg.data & 0xF0000000) >> 28;
    MOTOR_SPEED = (SYS_Reg.data & 0x0000FFFF) / 10;
    Reg.addr = CONTROLLER_FAULT_STATUS_ADDR;
    MCT8316A_GetReg(MCT8316A_Instance, &Reg);
    CONTROLLER_FAULT_STATUS = Reg.data;
    Reg.addr = GATE_DRIVER_FAULT_STATUS_ADDR;
    MCT8316A_GetReg(MCT8316A_Instance, &Reg);
    GATE_DRIVER_FAULT_STATUS = Reg.data;
    DWT_Delay(0.1);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 6;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
